package carcassonne.server.websocket.controller;

import carcassonne.game.mini.poker.HandsInfo;
import carcassonne.game.mini.poker.TexasHoldemPokerGame;
import carcassonne.game.mini.poker.GameLaunchInfo;
import carcassonne.game.mini.poker.TexasHoldemPokerGamePhaseInfo;
import carcassonne.game.player.Player;
import carcassonne.lobby.Room;
import carcassonne.server.ioc.Controller;
import carcassonne.server.ioc.RequestMapping;
import carcassonne.server.ioc.WebSocketMessageHandler;
import carcassonne.server.websocket.WebsocketContext;
import io.netty.channel.Channel;
import org.apache.log4j.Logger;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

@Controller
@RequestMapping(value = "game")
public class GameController {

    private static final Logger logger = Logger.getLogger(GameController.class);

    @WebSocketMessageHandler(path = "load_game_ready")
    public void LoadGameReady(WebsocketContext context) {
        Room room = context.room;
        if (room == null) {
            context.Error("empty room");
            return;
        }
        room.LoadGameReady(context.channel);
    }

    @WebSocketMessageHandler(path = "game_init_ready")
    public void GameInitReady(WebsocketContext context) {
        Channel channel = context.channel;
        Room room = context.room;
        if (!room.CheckPlayer(channel)) {
            context.Error("no such player!");
            return;
        }
        int key = context.GetInt();
        if (room.PlayerReady(channel, key)) {
            room.NotifyAll("/game/game_init_ready", null);
        }
    }

    @WebSocketMessageHandler(path = "end_turn")
    public void EndTurn(WebsocketContext context) {
        Room room = context.room;
        room.NotifyExcept(context.channel, context.raw);
    }

    @WebSocketMessageHandler(path = "texas_holdem_poker_buy_in")
    public void TexasHoldemPokerBuyIn(WebsocketContext context) {
        TexasHoldemPokerReady(context);
    }

    @WebSocketMessageHandler(path = "texas_holdem_poker_ready")
    public void TexasHoldemPokerReady(WebsocketContext context) {
        Channel channel = context.channel;
        Room room = context.room;
        if (!room.CheckPlayer(channel)) {
            context.Error("no such player!");
            return;
        }

        System.out.println(TexasHoldemPokerGame.class.hashCode() + " player ready " + channel.id().toString());
        if (room.PlayerReady(channel, TexasHoldemPokerGame.class.hashCode())) {
            System.out.println("all players ready");
            TexasHoldemPokerGame game = room.GetMiniGame("texas_holdem_poker", TexasHoldemPokerGame.class);
            Map<Channel, List<Integer>> hands = game.StartGame();
            for (Channel c : hands.keySet()) {
                GameLaunchInfo launchInfo = new GameLaunchInfo();
                launchInfo.id = game.ID;
                launchInfo.cards = hands.get(c);
                room.Notify(c, "/game/texas_holdem_poker_launch", launchInfo);
            }
        }
    }

    @WebSocketMessageHandler(path = "texas_holdem_poker_next_phase")
    public void TexasHoldemGetCards(WebsocketContext context) {
        Room room = context.room;
        TexasHoldemPokerGame game = room.GetMiniGame("texas_holdem_poker", TexasHoldemPokerGame.class);
//        List<String> params = context.GetStringArray();
        int phase = context.GetInt();
        TexasHoldemPokerGamePhaseInfo phaseInfo = new TexasHoldemPokerGamePhaseInfo();
        phaseInfo.id = game.ID;
        phaseInfo.phase = phase;
        phaseInfo.cards = game.GetPublicCards(phase);

        room.NotifyAll("/game/texas_holdem_poker_next_phase", phaseInfo);
    }

    @WebSocketMessageHandler(path = "texas_holdem_poker_show_hand")
    public void TexasHoldemShowHands(WebsocketContext context) {
        Channel channel = context.channel;
        Room room = context.room;

        Player player = room.FindPlayer(channel);
        if (player == null) {
            context.Error("no such player!");
            return;
        }

        TexasHoldemPokerGame game = room.GetMiniGame("texas_holdem_poker", TexasHoldemPokerGame.class);
        List<Integer> cards = game.GetHands(channel);

//        if (cards.isEmpty() || cards.size() > 2 || !game.CheckHands(channel, cards)) {
//            context.Error("wrong hand cards!");
//            return;
//        }

        HandsInfo handsInfo = new HandsInfo();
        handsInfo.id = game.ID;
        handsInfo.player = player.sequence;

        int mode = context.GetInt();
        if (mode == -1) {
            handsInfo.cards = cards;
        } else {
            if (cards.contains(mode)) {
                handsInfo.cards = new ArrayList<>();
                handsInfo.cards.add(mode);
            } else {
                context.Error("no such card <" + mode + ">");
            }
        }

        room.NotifyExcept(channel, "/game/texas_holdem_poker_show_hand", handsInfo);
    }
}
